package com.dkx.springbootwebsocket.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.simp.config.ChannelRegistration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.messaging.simp.stomp.StompCommand;
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
import org.springframework.messaging.support.ChannelInterceptor;
import org.springframework.messaging.support.MessageHeaderAccessor;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;

import java.security.Principal;
import java.util.Map;

/**
 * @Author:     杜科璇
 * @Description:  WebSocket配置类
 * @Date:    2025/10/31 18:42
 * @Version:    1.0
 */

@Configuration
@EnableWebSocketMessageBroker
@Slf4j
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        // 启用简单代理，指定目的地前缀
        config.enableSimpleBroker("/topic", "/queue", "/user");
        config.setApplicationDestinationPrefixes("/app");
        config.setUserDestinationPrefix("/user");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/ws")
                .setAllowedOriginPatterns("*")
                .withSockJS();
    }

    @Override
    public void configureClientInboundChannel(ChannelRegistration registration) {
        registration.interceptors(new ChannelInterceptor() {
            @Override
            public Message<?> preSend(Message<?> message, MessageChannel channel) {
                StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);

                if (StompCommand.CONNECT.equals(accessor.getCommand())) {
                    // 从连接头中获取用户ID
                    String userId = accessor.getFirstNativeHeader("userId");
                    log.info("CONNECT命令收到, userId: {}", userId);

                    if (userId != null) {
                        // 创建用户主体
                        Principal userPrincipal = new Principal() {
                            @Override
                            public String getName() {
                                return userId;
                            }
                        };

                        // 设置用户主体
                        accessor.setUser(userPrincipal);

                        // 将userId存储到session属性中
                        Map<String, Object> sessionAttributes = accessor.getSessionAttributes();
                        if (sessionAttributes != null) {
                            sessionAttributes.put("userId", userId);
                            log.info("已将userId存储到session属性: {}", userId);
                        }

                        log.info("用户主体设置完成: {}", userId);
                    }
                }

                // 记录SUBSCRIBE命令用于调试
                if (StompCommand.SUBSCRIBE.equals(accessor.getCommand())) {
                    String destination = accessor.getDestination();
                    Principal user = accessor.getUser();
                    String userId = user != null ? user.getName() : "unknown";
                    log.info("用户订阅: userId={}, destination={}", userId, destination);

                    // 通知消息服务订阅已建立
                    if (userId != null && !"unknown".equals(userId)) {
                        try {
                            // 这里需要获取WebSocketMessageService的实例
                            // 可以通过ApplicationContext或者直接注入
                            // 为了简单，我们暂时在WebSocketEventListener中处理
                        } catch (Exception e) {
                            log.error("处理订阅事件失败", e);
                        }
                    }
                }

                return message;
            }
        });
    }
}